//***************************************************************************//
//*
//* 内容摘要：音视频收发线程
//*	
//* 当前版本：V1.0		
//* 作    者：zhfayuan
//* 完成日期：2015-12-26
//**************************************************************************//

#if !defined(SDAVPROCESS_H)
#define SDAVPROCESS_H


#include "SDAVCommn.h"
#include "SDTermCommon.h"

#define CRYPT_METHOD_NONE 0
#define CRYPT_METHOD_SSL 1
#define CRYPT_METHOD_SM4 2

class CAVProcess : public CSDAVCommn
{

public:
	CAVProcess(BYTE byUserType,BOOL bUseInternalTimestamp = TRUE);
	virtual ~CAVProcess();

public:

	//对外接口
	BOOL	Create(char *strLocalIP, char *strRemoteIP, USHORT shLocalPort, USHORT shRemoteAvPort, USHORT shRemoteProxyPort, UINT unJitterBuffDelay, 
					FEC_REDUN_METHOD_TYPE eRedunMethod, UINT unRedunRatio, UINT unFecGroupSize);
	
	void	Close();

	//发送一帧视频码流，需附带H264起始码
	void	SendVideoStreamData(AVPACK_HEAD *pHead, UINT unLen, BYTE* buf, BYTE byIndex = 0, UINT unDts = 0);
	//发送一帧音频码率，建议ADTS格式
	void	SendAudioStreamData(AVPACK_HEAD *pHead, UINT unLen, BYTE* buf, BYTE byIndex = 0, UINT unDts = 0);

    void    UpdateCrypto(BYTE byCrypto,UINT use);

    //设置SM4加密密钥
    void    UpdateEncKey(UINT unToken,BYTE*key,UINT unLen);

    //设置SM4解密密钥
    void    UpdateDecKey(BYTE byIndex, UINT unToken, BYTE*key,UINT unLen);
       

	//UDP通讯统计数据获取
	//获得上行丢包率(视频通道)
	float	GetUpLostRatioOnVideoChannel();
	//获得下行丢包率(视频通道)
	float	GetDownLostRatioOnVideoChannel();
	//获得网络往返时延（视频通道）
	UINT	GetNetWorkDelayOnVideoChannel();
	//获得音视频上下行丢包率
	void	GetVideoAudioUpDownLostRatio(float &fVideoUpLostRatio, float &fVideoDownLostRatio, float &fAudioUpLostRatio, float &fAudioDownLostRatio);
	//获得音视频上下行码率
	void	GetVideoAudioUpDownBitrate(float &fVideoUpRate, float &fVideoDownRate, float &fAudioUpRate, float &fAudioDownRate);


	//本模块的输出接口,视频传输时，内部拆包拼包，bComplete用于指示该帧码流是否完整
	//bPrevTotalFrameLost用于指示当前帧之前是否出现整帧丢失的情况，这种情况下当从单帧丢包标志bComplete无法
	//检测出。对于音频传输一般数据量较小，不存在拆包拼包，音频包前后无参考性，一般无需告知外层丢包情况。
	virtual void OnRecvVideoStreamData(BYTE byCodec,BYTE byIndex,BYTE* data, UINT nLen, UINT unPTS, BOOL bComplete, BOOL bPrevTotalFrameLost, bool& bLostInGop) {}
	virtual void OnRecvAudioStreamData(BYTE byCodec,BYTE byIndex, BYTE* data, UINT nLen, UINT unPts) {}
    virtual void OnCheckedTokenUpdate(UINT64 unSrcUid,UINT unVkekToken,BYTE byIndex,BYTE byCrypto) {};

	//模块内部通过本接口查询当前设置的下行接收掩码
	virtual UINT64 GetAudioDownChannelsMask() { return AV_DOWN_MASK_DEFAULT;}
	virtual UINT64 GetVideoDownChannelsMask() { return AV_DOWN_MASK_DEFAULT;}

	//AV时间戳重新开始
	void ReInitAudioVideoEncoder();

#if SUPPORT_SEND_SMOOTH_PROCESS
	//告知视频帧率，便于内部实现发送smooth处理，注意该帧率一定要符合实际帧率
	//可以高于实际帧率，但不能低于实际帧率，否则将导致发送速度不足而队列满
	//不调用本函数时，默认关闭smooth处理
	void SetVideoFrameRateForSmoother(UINT unFrameRate);
#endif

private:
	static int VideoSendThreadClose(void* pParam);
	static int VideoSendThread(void* pParam);

	static int AudioSendThreadClose(void* pParam);
	static int AudioSendThread(void* pParam);

	static int VideoRecvThreadClose(void* pParam, void* pParam2);
	static int VideoRecvThread(void* pParam, void* pParam2);

	static int AudioRecvThreadClose(void* pParam, void* pParam2);
	static int AudioRecvThread(void* pParam, void* pParam2);


private:
	//void mfSendVideoNaluOnRtpChannel(BYTE byCodec,BYTE byIsKey,BYTE byCrypto,UINT unToken,char *pBuf, int nSize, int64_t nPts, int64_t nDts, UINT unFrameIndex, UINT unNaluCnt, UINT unNaluIndex, BYTE byIndex);
	//void mfSendAudioDataOnRtpChannel(BYTE byCodec,BYTE byCrypto,UINT unToken,char *pBuf, int nSize, int64_t nDts, BYTE byIndex);

	//将视频NALU单元通过RTP发送
	void mfSendVideoNaluOnRtpChannel(PacketHead head,BYTE byCrypto,UINT unToken,char *pBuf, int nSize, int64_t nPts, int64_t nDts,BYTE byPadding);
	//将音频码流帧通过RTP发送
	void mfSendAudioDataOnRtpChannel(PacketHead head,BYTE byCrypto,UINT unToken,char *pBuf, int nSize, int64_t nDts,BYTE byPadding);
private:
	//实现底层UDP接收AV后的处理虚函数
	void OnReciveAudioData(int nLen, BYTE *byBuf);
	void OnReciveVideoData(int nLen, BYTE *byBuf);
private:
    BYTE  m_byUserType;
private:
	//RTP音视频推送、接收线程相关
	CSDThread			m_VideoSendThread;
	CSDThread			m_AudioSendThread;

	CSDThread			m_VideoRecvThread[MAX_SUPPORT_DECODE_NUM];
	CSDThread			m_AudioRecvThread[MAX_SUPPORT_DECODE_NUM];

	volatile BOOL		m_bVideoSendThreadRun;
	volatile BOOL		m_bAudioSendThreadRun;

	volatile BOOL		m_bVideoRecvThreadRun[MAX_SUPPORT_DECODE_NUM];
	volatile BOOL		m_bAudioRecvThreadRun[MAX_SUPPORT_DECODE_NUM];

	volatile BOOL		m_bVideoRecvThreadRunning[MAX_SUPPORT_DECODE_NUM];
	volatile BOOL		m_bAudioRecvThreadRunning[MAX_SUPPORT_DECODE_NUM];

	int					m_iVideoRecvThreadId[MAX_SUPPORT_DECODE_NUM];
	int					m_iAudioRecvThreadId[MAX_SUPPORT_DECODE_NUM];


	//用于视频编码与视频发送线程之间交互数据的空满包队列
	DualQueId			m_ptVideoSendQue;
	//用于音频编码与音频发送线程之间交互数据的空满包队列
	DualQueId			m_ptAudioSendQue;
	//用于视频解码与视频接收线程之间交互数据的空满包队列
	DualQueId			m_ptVideoRecvQue[MAX_SUPPORT_DECODE_NUM];
	DualQueId			m_ptAudioRecvQue[MAX_SUPPORT_DECODE_NUM];

	//用于指定音视频jitterbuffer的相关参数
	struct timeval      m_tMinDelayVideoOutput;
	struct timeval      m_tDelayVideoOutput;
	struct timeval      m_tMaxDelayVideoOutput;

	struct timeval      m_tMinDelayAudioOutput;
	struct timeval      m_tDelayAudioOutput;
	struct timeval      m_tMaxDelayAudioOutput;
	bool				m_bDisableJitter;

	void*				m_pcsThread;

	//保护锁资源
	//Close动作与Create动作之间的互斥锁
	void*				m_pcsClose;
	bool				m_bClosed;

	//Close动作与外层发送接口之间的保护锁
	void*				m_pcsVideoEnc;
	void*				m_pcsAudioEnc;

	//帧序号
	UINT				m_unEncVideoFrameCount;
	UINT				m_unEncAudioFrameCount;

	//用于单帧单Slice时的码流拼接
	UINT				m_decFrameSeq[MAX_SUPPORT_DECODE_NUM];
	UINT				m_decPacketSeq[MAX_SUPPORT_DECODE_NUM];
	UINT				m_decPacketNum[MAX_SUPPORT_DECODE_NUM];
	UINT				m_decFrameLen[MAX_SUPPORT_DECODE_NUM];
	bool				m_bFirstPacket[MAX_SUPPORT_DECODE_NUM];
	bool				m_bPacketLost[MAX_SUPPORT_DECODE_NUM];
	bool				m_bTotalFrameLost[MAX_SUPPORT_DECODE_NUM];
	bool				m_bDecGetOneFrame[MAX_SUPPORT_DECODE_NUM];
	bool				m_bDecGetNewFrame[MAX_SUPPORT_DECODE_NUM];
	bool                m_bFindLostInGop[MAX_SUPPORT_DECODE_NUM];

    //存在各个通道的秘钥Token,通道秘钥Token与流Token一致时,开始解密数据
    UINT                m_unVkekToken[MAX_SUPPORT_DECODE_NUM];
    //存储各个通道的解码秘钥
    BYTE                m_byDecVek[MAX_SUPPORT_DECODE_NUM][16];

	//单帧单Slice模式时初始的时间戳(1KHZ时基),常见于移动端硬编码模式
	int64_t				m_nFirstTimestampVideo;
	//用于音频时间戳计算
	int64_t				m_nFirstTimestampAudio;

	//存放接收的成帧码流
	BYTE*				m_pFrameDecStreamBuf[MAX_SUPPORT_DECODE_NUM];
	UINT				m_nCurrTimestamp[MAX_SUPPORT_DECODE_NUM];
	void*				m_pRtpAvCom;

	//UINT				m_unSrcUid;
	//UINT				m_unDesUid;
	BYTE				m_byType;
	BOOL				m_bUseInternalTimestamp;

#if SUPPORT_SEND_SMOOTH_PROCESS
	//视频帧与帧之间的发送间隔(毫秒)
	UINT				m_unFrameTimeMs;
	//当前帧一批次发送的包数
	UINT				m_unPacketSendTogether;
	//当前帧开始发送的时间
	long				m_tFrameStartSendTime;
	//下一帧是否启用smooth处理
	BOOL				m_bEnableSmoothForNextFrame;
	//根据实际发送速度微调批次发送包数
	UINT				m_unDiffSendTime;
	//用于smooth处理的sleep处理
	CSDEvent            m_evtSmoother;
#endif

};
#endif // !defined(SDAVPROCESS_H)
